<cfcomponent displayname="KalendarDAO" hint="This CFC is intended to populate a calendar with event data. There are specific fields it requires to properly display the recordset!">


	<cfset variables.private = structNew() />

	<cffunction name="init" access="public" output="false" returntype="KalendarDAO">
		<cfargument name="KalendarConfig" type="any" required="true" hint="This is a reference to the main Kalendar Config component"/>
		<cfset variables.private.Config = arguments.KalendarConfig />
		<cfset variables.private.userEventDAO = CreateObject('component','UserEventDAO').init(arguments.KalendarConfig)/>
		<cfreturn this>
	</cffunction>
	
	<cffunction name="create" access="public" output="false" returntype="boolean">
		<cfargument name="Kalendar" type="any" required="true" />
		<cfset var qCreate = "" />
		<cfset arguments.Kalendar.setEventID(CreateUUID())/>
		<cfquery name="qCreate" datasource="#getConfig().getDSN()#">
			INSERT INTO tblKalendar
				(
				EventID,
				CategoryID,
				IsDeleted,
				IsPublic,
				IsFeatured,
				DateTimeCreated,
				StartDate,
				EndDate,
				IsAllDayEvent,
				ContactPhone,
				ContactName,
				ContactEmail,
				Title,
				Location,
				Teaser,
				ExternalURL,
				Description
				)
			VALUES
				(
				<cfqueryparam value="#arguments.Kalendar.getEventID()#" CFSQLType="cf_sql_varchar" />,
				<cfqueryparam value="#arguments.Kalendar.getCategoryID()#" CFSQLType="cf_sql_varchar" />,
				<cfqueryparam value="#yesNoFormat(arguments.Kalendar.getIsDeleted())#" CFSQLType="cf_sql_bit" />,
				<cfqueryparam value="#yesNoFormat(arguments.Kalendar.getIsPublic())#" CFSQLType="cf_sql_bit" />,
				<cfqueryparam value="#yesNoFormat(arguments.Kalendar.getIsFeatured())#" CFSQLType="cf_sql_bit" />,
				<cfqueryparam value="#CreateODBCDate(now())#" CFSQLType="cf_sql_timestamp" />,
				<cfqueryparam value="#CreateODBCDateTime(arguments.Kalendar.getStartDate())#" CFSQLType="cf_sql_timestamp" />,
				<cfqueryparam value="#CreateODBCDateTime(arguments.Kalendar.getEndDate())#" CFSQLType="cf_sql_timestamp" />,
				<cfqueryparam value="#YesNoFormat(arguments.Kalendar.getIsAllDayEvent())#" CFSQLType="cf_sql_bit"  />,
				<cfqueryparam value="#arguments.Kalendar.getContactPhone()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getContactPhone())#" />,
				<cfqueryparam value="#arguments.Kalendar.getContactName()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getContactName())#" />,
				<cfqueryparam value="#arguments.Kalendar.getContactEmail()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getContactEmail())#" />,
				<cfqueryparam value="#arguments.Kalendar.getTitle()#" CFSQLType="cf_sql_varchar" />,
				<cfqueryparam value="#arguments.Kalendar.getLocation()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getLocation())#" />,
				<cfqueryparam value="#arguments.Kalendar.getTeaser()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getTeaser())#" />,
				<cfqueryparam value="#arguments.Kalendar.getExternalURL()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getExternalURL())#" />,
				<cfqueryparam value="#arguments.Kalendar.getDescription()#" CFSQLType="cf_sql_longvarchar" />
				)
		</cfquery>
		<cfreturn true />
	</cffunction>

	<cffunction name="read" access="public" output="false" returntype="void">
		<cfargument name="Kalendar" type="any" required="true" />
		<cfset var qRead = "" />
		<cfset var strReturn = structNew() />
		<cfquery name="qRead" datasource="#getConfig().getDSN()#">
			SELECT
				tblKalendar.EventID,
				tblKalendar.CategoryID,
				tblKalendar.IsDeleted,
				tblKalendar.IsPublic,
				tblKalendar.IsFeatured,
				tblKalendar.DateTimeCreated,
				tblKalendar.StartDate,
				tblKalendar.EndDate,
				tblKalendar.IsAllDayEvent,
				tblKalendar.ContactPhone,
				tblKalendar.ContactName,
				tblKalendar.ContactEmail,
				tblKalendar.Title,
				tblKalendar.Location,
				tblKalendar.Teaser,
				tblKalendar.ExternalURL,
				tblKalendar.Description,
				UserEvents.UserID,
				UserEvents.UserRole AS Role
			FROM	dbo.tblKalendar tblKalendar
			JOIN	dbo.UserEvents UserEvents ON UserEvents.EventID = tblKalendar.EventID 
			WHERE	tblKalendar.EventID = <cfqueryparam value="#arguments.Kalendar.getEventID()#" CFSQLType="cf_sql_varchar" />
		</cfquery>
		<cfif qRead.recordCount>
			<cfset strReturn = queryRowToStruct(qRead)>
			<cfset arguments.Kalendar.init(argumentCollection=strReturn)>
		</cfif>
	</cffunction>

	<cffunction name="update" access="public" output="false" returntype="boolean">
		<cfargument name="Kalendar" type="any" required="true" />
		<cfset var qUpdate = "" />
		<cfquery name="qUpdate" datasource="#getConfig().getDSN()#">
			UPDATE	tblKalendar
			SET
				CategoryID = <cfqueryparam value="#arguments.Kalendar.getCategoryID()#" CFSQLType="cf_sql_varchar" />,
				IsDeleted = <cfqueryparam value="#YesNoFormat(arguments.Kalendar.getIsDeleted())#" CFSQLType="cf_sql_bit" />,
				IsPublic = <cfqueryparam value="#YesNoFormat(arguments.Kalendar.getIsPublic())#" CFSQLType="cf_sql_bit" />,
				IsFeatured = <cfqueryparam value="#YesNoFormat(arguments.Kalendar.getIsFeatured())#" CFSQLType="cf_sql_bit"  />,
				StartDate = <cfqueryparam value="#CreateODBCDateTime(arguments.Kalendar.getStartDate())#" CFSQLType="cf_sql_timestamp" />,
				EndDate = <cfqueryparam value="#CreateODBCDateTime(arguments.Kalendar.getEndDate())#" CFSQLType="cf_sql_timestamp" />,
				IsAllDayEvent = <cfqueryparam value="#YesNoFormat(arguments.Kalendar.getIsAllDayEvent())#" CFSQLType="cf_sql_bit"  />,
				ContactPhone = <cfqueryparam value="#arguments.Kalendar.getContactPhone()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getContactPhone())#" />,
				ContactName = <cfqueryparam value="#arguments.Kalendar.getContactName()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getContactName())#" />,
				ContactEmail = <cfqueryparam value="#arguments.Kalendar.getContactEmail()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getContactEmail())#" />,
				Title = <cfqueryparam value="#arguments.Kalendar.getTitle()#" CFSQLType="cf_sql_varchar" />,
				Location = <cfqueryparam value="#arguments.Kalendar.getLocation()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getLocation())#" />,
				Teaser = <cfqueryparam value="#arguments.Kalendar.getTeaser()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getTeaser())#" />,
				ExternalURL = <cfqueryparam value="#arguments.Kalendar.getExternalURL()#" CFSQLType="cf_sql_varchar" null="#not len(arguments.Kalendar.getExternalURL())#" />,
				Description = <cfqueryparam value="#arguments.Kalendar.getDescription()#" CFSQLType="cf_sql_longvarchar" />
			WHERE	EventID = <cfqueryparam value="#arguments.Kalendar.getEventID()#" CFSQLType="cf_sql_varchar" />
		</cfquery>
		<cfreturn true/>
	</cffunction>

	<cffunction name="delete" access="public" output="false" returntype="boolean">
		<cfargument name="Kalendar" type="any" required="true" />

		<cfset var qDelete = "">
		<cftry>
			<cfset getUserEventDAO().delete(arguments.Kalendar)/>
			<cfquery name="qDelete" datasource="#getConfig().getDSN()#">
						
			UPDATE
				tblKalendar
			SET
				IsDeleted = 1
			WHERE
				EventID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.Kalendar.getEventID()#" />
			</cfquery>
			<cfcatch type="database">
				<cfreturn false />
			</cfcatch>
		</cftry>
		<cfreturn true />
	</cffunction>

	<cffunction name="exists" access="public" output="false" returntype="boolean">
		<cfargument name="Kalendar" type="any" required="true" />

		<cfset var qExists = "">
		<cfquery name="qExists" datasource="#getConfig().getDSN()#" maxrows="1">
			SELECT count(1) as idexists
			FROM	tblKalendar
			WHERE	EventID = <cfqueryparam value="#arguments.Kalendar.getEventID()#" CFSQLType="cf_sql_varchar" />
		</cfquery>

		<cfif qExists.idexists>
			<cfreturn true />
		<cfelse>
			<cfreturn false />
		</cfif>
	</cffunction>

	<cffunction name="save" access="public" output="false" returntype="boolean">
		<cfargument name="Kalendar" type="any" required="true" />
		
		<cfset var success = false />
		<cfif exists(arguments.Kalendar)>
			<cfset success = update(arguments.Kalendar) />
		<cfelse>
			<cfset success = create(arguments.Kalendar) />
		</cfif>
		<cfif success>
			<cfset success = getUserEventDAO().save(arguments.Kalendar)/>
		</cfif>
		<cfreturn success />
	</cffunction>

	<!--- get calendar --->
	<cffunction access="public" 
		name="getCalendar" 
		output="true" 
		returntype="array" 
		displayname="getCalendar" 
		hint="gets data for calendar and converts to an array of structs">
			
		<cfargument name="view" 
				type="string" 
				required="true"
				hint="sets the calendar to display week or month view" />
				
		<cfargument name="StartPeriod" 
				type="date" 
				required="yes"
				hint="begining of this interval." />
				
		<cfargument name="EndPeriod" 
				type="date" 
				required="yes"
				hint="end of this interval." />
				
		<cfargument name="User" 
				type="struct" 
				required="yes"
				hint="User bean" />
				
		<cfargument name="CategoryID" 
				type="numeric" 
				required="yes"
				hint="allows querying of records by category." />
				
		<cfargument name="Timezones" 
				type="Timezones" 
				required="yes"
				hint="Timezones class" />
		
		<cfscript>
			var CalendarEvents = ArrayNew(1);
			var ArrayCount = 0;
			var qGetCalendar = 0;
		</cfscript>
		<!--- query for events --->
		<cfquery name="qGetCalendar" datasource="#getConfig().getDSN()#" result="x">

			SELECT
				tblKalendar.*,
				tblKalendarCategories.CategoryName,
				tblKalendarCategories.CategoryBGColor,
				tblKalendarCategories.CategoryTextColor,
				editable = CASE
								WHEN UserEvents.UserRole < <cfqueryparam cfsqltype="cf_sql_integer" value="#Val(arguments.user.getRole())#"/> THEN 1
								WHEN UserEvents.UserID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(arguments.user.getUserID())#"/> THEN 1
								ELSE 0
							END <cfif CompareNoCase(getConfig().getDBType(),'MYSQL') EQ 0>CASE</cfif>
			FROM
				UserEvents
				INNER JOIN tblKalendar ON tblKalendar.EventID = UserEvents.EventID
				LEFT JOIN tblKalendarCategories ON tblKalendarCategories.CategoryID = tblKalendar.CategoryID 
			WHERE
				tblKalendar.IsDeleted = 0
				AND UserEvents.IsDeleted = 0

			AND
				(
					(
						tblKalendar.StartDate >= <cfqueryparam cfsqltype="cf_sql_timestamp" value="#arguments.StartPeriod#" />
					OR
				  		tblKalendar.EndDate >= <cfqueryparam cfsqltype="cf_sql_timestamp" value="#arguments.StartPeriod#" />
				  	)
			AND
					(
						tblKalendar.StartDate <= <cfqueryparam cfsqltype="cf_sql_timestamp" value="#arguments.EndPeriod#" />
					OR
						tblKalendar.EndDate <= <cfqueryparam cfsqltype="cf_sql_timestamp" value="#arguments.EndPeriod#" />
					)
				)

			AND (tblKalendar.IsPublic = 1 OR UserEvents.UserID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Trim(arguments.user.getUserID())#"/>)
			<cfif arguments.CategoryID neq 0>
			AND
				tblKalendarCategories.CategoryID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.CategoryID#" />
			</cfif>
			ORDER BY 
				StartDate,
				EndDate

		</cfquery> 
		<!--- convert query to array --->
		<cfoutput query="qGetCalendar" group="EventID">
			<cfscript>
				ArrayCount = ArrayCount + 1;
				CalendarEvents[ArrayCount] = StructNew();
			</cfscript>
			
			<cfoutput>
				<cfscript>
					CalendarEvents[ArrayCount].IsAllDayEvent = IsAllDayEvent;
					CalendarEvents[ArrayCount].Editable = Editable;
					CalendarEvents[ArrayCount].StartDate = arguments.timezones.castFromUTC(StartDate,arguments.user.getTimezone());
					CalendarEvents[ArrayCount].StartTime = TimeFormat(CalendarEvents[ArrayCount].StartDate);
					CalendarEvents[ArrayCount].EndDate = arguments.timezones.castFromUTC(EndDate,arguments.user.getTimezone());
					CalendarEvents[ArrayCount].EndTime = TimeFormat(CalendarEvents[ArrayCount].EndDate);
					CalendarEvents[ArrayCount].EventIDLabel = "EventID";
					CalendarEvents[ArrayCount].EventID = EventID;
					CalendarEvents[ArrayCount].Title = Trim(Title);
					CalendarEvents[ArrayCount].Teaser = Trim(Teaser);
					CalendarEvents[ArrayCount].Description = Trim(Description);
					CalendarEvents[ArrayCount].Location = Trim(Location);
					CalendarEvents[ArrayCount].ExternalURL = Trim(ExternalURL);
					CalendarEvents[ArrayCount].CategoryName = CategoryName;
					CalendarEvents[ArrayCount].ContactName = ContactName;
					CalendarEvents[ArrayCount].ContactPhone = ContactPhone;
					CalendarEvents[ArrayCount].ContactEmail = ContactEmail;
					CalendarEvents[ArrayCount].CategoryBGColor = CategoryBGColor;
					CalendarEvents[ArrayCount].CategoryTextColor = CategoryTextColor;
				</cfscript>
			</cfoutput>
		</cfoutput>
		
		<cfreturn CalendarEvents /> 

	</cffunction>
	
	
	<!--- Function KalendarXML --->
	<cffunction access="public" 
			name="loadKalendarXML" 
			output="false" 
			returntype="xml" 
			displayname="KalendarXML" 
			hint="Creates XML from resultset of getCalendar">
			
		<cfargument name="view" 
				type="string" 
				required="true"
				hint="sets the calendar to display week or month view" />
				
		<cfargument name="LinkDate" 
				type="date" 
				required="yes"
				hint="Currently Selected Date." />
								
		<cfargument name="StartPeriod" 
				type="date" 
				required="yes"
				hint="begining of this interval." />
				
		<cfargument name="EndPeriod" 
				type="date" 
				required="yes"
				hint="end of this interval." />
							
		<cfargument name="CategoryID" 
				type="numeric" 
				required="yes"
				hint="allows querying of records by category." />
				
		<cfscript>
			var publishDate = DateConvert("local2Utc", Now());
			var eventdate = "";
			var description = "";
			var category = "";
			var eventid = "";
			var rssFeed = "";
			var KalendarData = "";
			var title = "";
			var tempUser = StructNew();
			tempUser.userID = 0;
			tempUser.role = 3;
			tempUser.timezone = 'America/New_York';
			publishDate = DateFormat(publishDate, "ddd, dd mmm yyyy") & " " & TimeFormat(publishDate, "HH:mm:ss") & " GMT";
			KalendarData = getCalendar("month", arguments.StartPeriod, arguments.EndPeriod, CreateObject('component','User').init(argumentcollection=tempUser), arguments.CategoryID);
		</cfscript>
		
		<cfxml variable="rssFeed"><cfprocessingdirective suppresswhitespace="yes"><rss version="2.0">
	<channel>
		<title>Kalendar of Events for <cfoutput>#DateFormat(arguments.LinkDate, "mmmm yyyy")#</cfoutput></title>
		<link>http://<cfoutput>#cgi.SERVER_NAME##cgi.SCRIPT_NAME#</cfoutput></link>
		<description>Latest Events</description>
		<language>en-us</language>
		<copyright>Copyright 2006 TJ Downes</copyright>
		<pubDate><cfoutput>#publishDate#</cfoutput></pubDate>
		<lastBuildDate><cfoutput>#publishDate#</cfoutput></lastBuildDate>
		<generator>Kalendar</generator>
		<docs>http://cfopen.org/docman/?group_id=102</docs>
		<managingEditor><cfoutput>#Trim(getConfig().getRSSEditor())#</cfoutput></managingEditor>
		<webMaster><cfoutput>#Trim(getConfig().getRSSWebmaster())#</cfoutput></webMaster>
		<cfloop index="i" from="1" to="#ArrayLen(KalendarData)#">
				<cfif Month(KalendarData[i].StartDate) eq Month(LinkDate)>
					<cfscript>
					  title = XMLFormat(KalendarData[i].Title);
					  if(Len(Trim(KalendarData[i].StartTime))) {
					  	eventdate = DateConvert("local2Utc", DateFormat(KalendarData[i].StartDate, "m/d/yyyy") & " " & TimeFormat( KalendarData[i].StartTime ) );
						} else {
						eventdate = DateConvert("local2Utc", KalendarData[i].StartDate);
						}
					  eventdate = DateFormat(eventdate, "ddd, dd mmm yyyy") & " " & TimeFormat(eventdate, "HH:mm:ss") & " GMT";
					  description = XMLFormat(KalendarData[i].Description);
					  category = XMLFormat(Trim(KalendarData[i].CategoryName));
					  eventid = KalendarData[i].EventID;
					</cfscript><cfoutput><item>
			<title>#title#</title>
			<description>#description#</description>
			<link>http://#cgi.SERVER_NAME#/#cgi.SCRIPT_NAME#</link>
			<category>#category#</category>
			<pubDate>#eventdate#</pubDate>
			<guid>http://#cgi.SERVER_NAME##Replace(cgi.SCRIPT_NAME, ListLast(cgi.SCRIPT_NAME, "/"), "eventDetails.cfm")#?eventid=#eventid#</guid>
		</item></cfoutput></cfif></cfloop>
	</channel>
</rss></cfprocessingdirective></cfxml>
		<cfreturn rssFeed />
				
	</cffunction>


	<cffunction name="queryRowToStruct" access="private" output="false" returntype="struct">
		<cfargument name="qry" type="query" required="true">
		
		<cfscript>
			/**
			 * Makes a row of a query into a structure.
			 * 
			 * @param query 	 The query to work with. 
			 * @param row 	 Row number to check. Defaults to row 1. 
			 * @return Returns a structure. 
			 * @author Nathan Dintenfass (nathan@changemedia.com) 
			 * @version 1, December 11, 2001 
			 */
			//by default, do this to the first row of the query
			var row = 1;
			//a var for looping
			var ii = 1;
			//the cols to loop over
			var cols = listToArray(qry.columnList);
			//the struct to return
			var stReturn = structnew();
			//if there is a second argument, use that for the row number
			if(arrayLen(arguments) GT 1)
				row = arguments[2];
			//loop over the cols and build the struct from the query row
			for(ii = 1; ii lte arraylen(cols); ii = ii + 1){
				stReturn[cols[ii]] = qry[cols[ii]][row];
			}		
			//return the struct
			return stReturn;
		</cfscript>
	</cffunction>
	
	<cffunction name="getUserEventDAO" access="public" output="false" returntype="any">
		<cfreturn variables.private.UserEventDAO />
	</cffunction>
	
	<cffunction name="getConfig" access="public" output="false" returntype="any">
		<cfreturn variables.private.Config />
	</cffunction>
</cfcomponent>